package com.huashi.dealer.core.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.Random;
import java.awt.GraphicsEnvironment;

/**
 * 验证码工具类
 * 用于生成验证码图片
 *
 * @author 谭陈强
 * @since 2025-07-30
 */
public class CaptchaUtil {

    /**
     * 验证码图片宽度
     */
    private static final int WIDTH = 120;

    /**
     * 验证码图片高度
     */
    private static final int HEIGHT = 40;

    /**
     * 验证码字体大小
     */
    private static final int FONT_SIZE = 20;

    /**
     * 生成验证码图片
     *
     * @param code 验证码文本
     * @return base64编码的图片数据
     */
    public static String generateCaptchaImage(String code) {
        try {
            // 创建图片缓冲区
            BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = image.createGraphics();

            // 设置抗锯齿
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

            // 设置背景色
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, WIDTH, HEIGHT);

            // 绘制干扰线
            drawInterferenceLines(g2d);

            // 绘制验证码文字（使用兼容的字体）
            try {
                drawCaptchaText(g2d, code);
            } catch (Exception e) {
                // 如果字体绘制失败，使用最基本的绘制方式
                drawCaptchaTextBasic(g2d, code);
            }

            // 绘制干扰点
            drawInterferencePoints(g2d);

            g2d.dispose();

            // 转换为base64
            return convertToBase64(image);

        } catch (Exception e) {
            throw new RuntimeException("生成验证码图片失败", e);
        }
    }
    
    /**
     * 绘制验证码文字（最基本版本，完全不依赖字体）
     */
    private static void drawCaptchaTextBasic(Graphics2D g2d, String code) {
        Random random = new Random();
        
        // 使用最基本的字体
        Font font = new Font("Monospaced", Font.BOLD, FONT_SIZE);
        g2d.setFont(font);

        // 计算文字起始位置
        FontMetrics fontMetrics = g2d.getFontMetrics();
        int textWidth = fontMetrics.stringWidth(code);
        int startX = (WIDTH - textWidth) / 2;
        int startY = HEIGHT / 2 + fontMetrics.getAscent() / 2;

        // 绘制每个字符
        for (int i = 0; i < code.length(); i++) {
            char c = code.charAt(i);
            
            // 随机颜色
            Color color = new Color(
                random.nextInt(100) + 50,
                random.nextInt(100) + 50,
                random.nextInt(100) + 50
            );
            g2d.setColor(color);

            // 随机旋转角度
            double angle = (random.nextDouble() - 0.5) * 0.3;
            AffineTransform originalTransform = g2d.getTransform();
            
            int charX = startX + fontMetrics.charWidth(c) * i;
            int charY = startY + random.nextInt(6) - 3;
            
            g2d.rotate(angle, charX, charY);
            g2d.drawString(String.valueOf(c), charX, charY);
            g2d.setTransform(originalTransform);
        }
    }

    /**
     * 绘制干扰线
     */
    private static void drawInterferenceLines(Graphics2D g2d) {
        Random random = new Random();
        g2d.setColor(Color.LIGHT_GRAY);
        
        for (int i = 0; i < 6; i++) {
            int x1 = random.nextInt(WIDTH);
            int y1 = random.nextInt(HEIGHT);
            int x2 = random.nextInt(WIDTH);
            int y2 = random.nextInt(HEIGHT);
            
            g2d.setStroke(new BasicStroke(1.0f));
            g2d.drawLine(x1, y1, x2, y2);
        }
    }

    /**
     * 绘制验证码文字
     */
    private static void drawCaptchaText(Graphics2D g2d, String code) {
        Random random = new Random();
        
        // 使用更兼容的字体设置，解决Linux服务器字体问题
        Font font = getCompatibleFont();
        g2d.setFont(font);

        // 计算文字起始位置
        FontMetrics fontMetrics = g2d.getFontMetrics();
        int textWidth = fontMetrics.stringWidth(code);
        int startX = (WIDTH - textWidth) / 2;
        int startY = HEIGHT / 2 + fontMetrics.getAscent() / 2;

        // 绘制每个字符
        for (int i = 0; i < code.length(); i++) {
            char c = code.charAt(i);
            
            // 随机颜色
            Color color = new Color(
                random.nextInt(100) + 50,
                random.nextInt(100) + 50,
                random.nextInt(100) + 50
            );
            g2d.setColor(color);

            // 随机旋转角度
            double angle = (random.nextDouble() - 0.5) * 0.3;
            AffineTransform originalTransform = g2d.getTransform();
            
            int charX = startX + fontMetrics.charWidth(c) * i;
            int charY = startY + random.nextInt(6) - 3;
            
            g2d.rotate(angle, charX, charY);
            g2d.drawString(String.valueOf(c), charX, charY);
            g2d.setTransform(originalTransform);
        }
    }
    
    /**
     * 获取兼容的字体
     * 解决Linux服务器字体问题
     */
    private static Font getCompatibleFont() {
        // 尝试使用系统默认字体
        Font font = new Font(Font.SANS_SERIF, Font.BOLD, FONT_SIZE);
        
        // 如果默认字体不可用，尝试其他字体
        if (!font.canDisplay('A')) {
            // 尝试使用Dialog字体
            font = new Font(Font.DIALOG, Font.BOLD, FONT_SIZE);
        }
        
        // 如果还是不可用，使用Monospaced字体
        if (!font.canDisplay('A')) {
            font = new Font(Font.MONOSPACED, Font.BOLD, FONT_SIZE);
        }
        
        // 最后的备选方案：使用默认字体
//        if (!font.canDisplay('A')) {
//            font = new Font(Font.DEFAULT_FONT, Font.BOLD, FONT_SIZE);
//        }
        
        // 如果所有字体都不可用，使用最基本的字体
        if (!font.canDisplay('A')) {
            // 获取系统所有可用字体
            try {
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                Font[] fonts = ge.getAllFonts();
                
                if (fonts.length > 0) {
                    font = fonts[0].deriveFont(Font.BOLD, FONT_SIZE);
                } else {
                    // 最后的备选方案：创建一个简单的字体
                    font = new Font("Serif", Font.BOLD, FONT_SIZE);
                }
            } catch (Exception e) {
                // 如果获取字体环境失败，使用最基本的字体
                font = new Font("Serif", Font.BOLD, FONT_SIZE);
            }
        }
        
        return font;
    }

    /**
     * 绘制干扰点
     */
    private static void drawInterferencePoints(Graphics2D g2d) {
        Random random = new Random();
        g2d.setColor(Color.LIGHT_GRAY);
        
        for (int i = 0; i < 50; i++) {
            int x = random.nextInt(WIDTH);
            int y = random.nextInt(HEIGHT);
            g2d.fillOval(x, y, 1, 1);
        }
    }

    /**
     * 将图片转换为base64编码
     */
    private static String convertToBase64(BufferedImage image) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", baos);
        byte[] imageBytes = baos.toByteArray();
        baos.close();
        
        String base64 = Base64.getEncoder().encodeToString(imageBytes);
        return "data:image/png;base64," + base64;
    }

    /**
     * 生成验证码并返回图片
     *
     * @param length 验证码长度
     * @return 包含验证码和图片的对象
     */
    public static CaptchaResult generateCaptcha(int length) {
        String code = PasswordUtil.generateRandomCode(length);
        String imageBase64 = generateCaptchaImage(code);
        
        return new CaptchaResult(code, imageBase64);
    }

    /**
     * 验证码结果类
     */
    public static class CaptchaResult {
        private final String code;
        private final String imageBase64;

        public CaptchaResult(String code, String imageBase64) {
            this.code = code;
            this.imageBase64 = imageBase64;
        }

        public String getCode() {
            return code;
        }

        public String getImageBase64() {
            return imageBase64;
        }
    }
    
    /**
     * 检查字体可用性
     * 在应用启动时调用，用于诊断字体问题
     */
    public static void checkFontAvailability() {
        try {
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            Font[] fonts = ge.getAllFonts();
            System.out.println("系统可用字体数量: " + fonts.length);
            
            // 检查常用字体
            String[] commonFonts = {"Arial", "SansSerif", "Dialog", "Monospaced", "Serif"};
            for (String fontName : commonFonts) {
                Font font = new Font(fontName, Font.BOLD, 12);
                boolean canDisplay = font.canDisplay('A');
                System.out.println("字体 " + fontName + " 可用: " + canDisplay);
            }
        } catch (Exception e) {
            System.err.println("字体检查失败: " + e.getMessage());
        }
    }
} 